package com.guet.careapp.service.impl;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.ServiceHelper;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import cn.jpush.api.push.model.notification.PlatformNotification;
import com.google.gson.Gson;
import com.guet.careapp.common.Constants;
import com.guet.careapp.controller.rest.common.errorCode.Error;
import com.guet.careapp.controller.rest.common.errorCode.ErrorCodeFactory;
import com.guet.careapp.pojo.TUserInfo;
import com.guet.careapp.pojo.rest.Introduction;
import com.guet.careapp.service.IPushService;
import com.guet.careapp.utils.ConvertUtils;
import com.guet.careapp.utils.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by LXM on 2017/10/30.
 *
 * @author LXM
 * @version 1.0
 * @description
 * @datetime 11:34
 */
@Service
public class PushServiceImpl implements IPushService {

    //极光推送API的地址
    final String JPUSH_HOST = Constants.JPUSH_HOST;
    final String MASTER_SECRET = Constants.MASTER_SECRET;
    final String APP_KEY = Constants.APP_KEY;
    Logger logger = LoggerFactory.getLogger(PushServiceImpl.class);


    @Override
    public Error PushMessageForAll(Introduction instruction) {
        //获取配置
        ClientConfig clientConfig = ClientConfig.getInstance();
        //实例化Client
        JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        //创建消息的实体
        Message message = Message.content(new Gson().toJson(instruction));
        //创建要发送的实体
        final PushPayload payload = buildPushObject_all(message);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            // 如果使用 NettyHttpClient，需要手动调用 close 方法退出进程
            // jpushClient.close();
        } catch (APIConnectionException e) {
            logger.error("Connection error. Should retry later. ", e);
            logger.error("Sendno: " + payload.getSendno());
            return Error.Unkonwn;

        } catch (APIRequestException e) {
            printAPIException(e);
            logger.error("Sendno: " + payload.getSendno());
            return Error.Unkonwn;
        }
        return Error.Success;
    }

    @Override
    public Error PushMessageForUsers(Introduction instruction, String... users) {

        //获取配置
        ClientConfig clientConfig = ClientConfig.getInstance();
        //实例化Client
        JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        //创建消息的实体
//    Map map = ConvertUtils.jsonToMap(instruction.getContent());
        Message message = Message.content(new Gson().toJson(instruction));
        //创建要发送的实体
        final PushPayload payload = buildPushDrug_byUsers(instruction, users);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got results - " + result);
            // 如果使用 NettyHttpClient，需要手动调用 close 方法退出进程
            // jpushClient.close();
        } catch (APIConnectionException e) {
            logger.error("Connection error. Should retry later. ", e);
            logger.error("Sendno: " + payload.getSendno());
            return Error.Unkonwn;

        } catch (APIRequestException e) {
            printAPIException(e);
            logger.error("Sendno: " + payload.getSendno());
            return Error.Unkonwn;
        }
        return Error.Success;

    }

    /**
     * 吃药提醒。把要发送的显示的图片和时间放到introduction的content中，发送给users
     */
    @Override
    public Error PushTimeToEatMedicines(Introduction introduction, String... users) {

        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushDrug_byUsers(introduction, users);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;

    }

    /**
     * 这个是摔倒通知！
     *
     * @param users
     * @param oldsName
     * @return
     */
    @Override
    public Error PushTumble(List<String> users, String oldsName) {
        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushTumble(users, oldsName);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;
    }

    /**
     * 请求紧急联系的通知
     *
     * @param devicesIDs
     * @param oldsName
     * @return
     */
    @Override
    public Error PushEmergency(List<String> devicesIDs, String oldsName) {
        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushEmegency(devicesIDs, oldsName);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;
    }

    /**
     * 这个是请求位置的通知
     *
     * @param introduction
     * @param deviceID
     * @return
     */
    @Override
    public Error PushLocationRequest(Introduction introduction, String... deviceID) {

        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushLocationRequest(introduction, deviceID);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;

    }

    /**
     * 这个是回应位置的通知
     *
     * @param introduction
     * @param deviceID
     * @return
     */
    @Override
    public Error PushLocationResponse(Introduction introduction, String... deviceID) {
        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushLocationResponce(introduction, deviceID);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;
    }

    /**
     * 推送任意的消息到指定到用户设备ID
     *
     * @param deviceId
     * @return
     */
    @Override
    public Error PushCustomMessage(String message, String... deviceId) {
        ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildCustomMessage(message, deviceId);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
            APIConnectionException(e, payload);

        } catch (APIRequestException e) {
            printAPIException(e);
        }
        return Error.Success;
    }

    /**
     * 打印通用错误
     *
     * @param e
     */
    private void printAPIException(APIRequestException e) {

        logger.error("Error response from JPush server. Should review and fix it. ", e);
        logger.info("HTTP Status: " + e.getStatus());
        logger.info("Error Code: " + e.getErrorCode());
        logger.info("Error Message: " + e.getErrorMessage());
        logger.info("Msg ID: " + e.getMsgId());

    }

    /**
     * 打印通用错误
     *
     * @param e
     * @param p
     */
    private void APIConnectionException(APIConnectionException e, PushPayload p) {

        logger.error("Connection error. Should retry later. ", e);
        logger.error("Sendno: " + p.getSendno());

    }


    /**
     * 向所有用户广播信息
     *
     * @param message
     * @return
     */
    private PushPayload buildPushObject_all(Message message) {

        return PushPayload.newBuilder()
                .setCid(MD5Util.MD5(System.currentTimeMillis() + ""))
                .setPlatform(Platform.android())
                .setAudience(Audience.all())
                .setMessage(message)
                .setOptions(Options.newBuilder().setTimeToLive(1000).build())
                .build();
    }

    /**
     * 构建吃药的push
     *
     * @param introduction
     * @param registration_id
     * @return
     */
    private PushPayload buildPushDrug_byUsers(Introduction introduction, String... registration_id) {
        Object drupInfomation = introduction.getContent();
        //解析Json
        Map map = ConvertUtils.jsonToMap(drupInfomation.toString());

        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(registration_id))
                .setPlatform(Platform.android())
                .setNotification((Notification.android("您的家人提醒您，现在该吃药了", "吃药提醒", null)))
                .setMessage(Message.newBuilder()
                        .addExtras(map)
                        .setMsgContent("this is a message")
                        .build())
                .build();

    }


//    public static PushPayload buildPushObject_android_and_ios() {
//        Map<String, String> extras = new HashMap<String, String>();
//        //加入额外的参数
//        extras.put("test", "https://community.jiguang.cn/push");
//        return PushPayload.newBuilder()
//                .setPlatform(Platform.android_ios())
//                .setAudience(Audience.all())
//                .setNotification(Notification.newBuilder()
//                        .setAlert("alert content")
//                        .addPlatformNotification(AndroidNotification.newBuilder()
//                                .setTitle("Android Title")
//                                .addExtras(extras).build())
//                        .addPlatformNotification(IosNotification.newBuilder()
//                                .incrBadge(1)
//                                .addExtra("extra_key", "extra_value").build())
//                        .build())
//                .build();
//    }

    /**
     * 构建摔倒的推送
     *
     * @param list
     * @param oldsName
     * @return
     */
    public PushPayload buildPushTumble(List<String> list, String oldsName) {
        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(list))
                .setPlatform(Platform.android())
                .setNotification((Notification.android("系统检测到您的被监护人" + oldsName + "疑似摔倒，请致电立即核查！", "紧急提醒", null)))
                .build();
    }

    /**
     * 构建紧急呼救的推送
     *
     * @param list
     * @param oldsName
     * @return
     */
    public PushPayload buildPushEmegency(List<String> list, String oldsName) {
        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(list))
                .setPlatform(Platform.android())
                .setNotification((Notification.android("系统检测到您的被监护人" + oldsName + "遇到紧急情况！", "紧急提醒", null)))
                .build();
    }


    /**
     * 构建查询老人位置的推送
     *
     * @param introduction
     * @param registration_id
     * @return
     */
    public PushPayload buildPushLocationRequest(Introduction introduction, String... registration_id) {
        Object drupInfomation = introduction.getContent();
        //解析Json
        Map map = (Map) drupInfomation;

        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(registration_id))
                .setPlatform(Platform.android())
                .setNotification((Notification.android("您的家人正在搜索您的位置，已自动发送您当前位置，如有疑问请联系您的监护人", "位置服务提醒", null)))
                .setMessage(Message.newBuilder()
                        .addExtras(map)
                        .setMsgContent(drupInfomation.toString())
                        .build())
                .build();
    }


    public PushPayload buildPushLocationResponce(Introduction introduction, String... registration_id) {
        Object drupInfomation = introduction.getContent();
        //解析Json
        Map map = (Map) drupInfomation;

        Map detailMap = (Map) drupInfomation;
        ;

        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(registration_id))
                .setPlatform(Platform.android())
                .setNotification((Notification.android("您的被监护人当前位置为：" + detailMap.get("Location") + "", "位置服务提醒", null)))
                .setMessage(Message.newBuilder()
                        .addExtras(map)
                        .setMsgContent(ConvertUtils.map2String(detailMap))
                        .build())
                .build();
    }


    public PushPayload buildCustomMessage(String message, String... registration_id) {
        return PushPayload.newBuilder()
                .setAudience(Audience.registrationId(registration_id))
                .setPlatform(Platform.android())
                .setMessage(Message.newBuilder()
                        .setMsgContent(message)
                        .build())
                .build();
    }
}
